package com.hy.mybatisplus.config;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;

/**
 * @author hy
 * @date 2020/09/29  9:30 AM
 */

@Data
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public abstract class BaseRequest<T> implements Serializable {
    private static final Logger LOGGER = LoggerFactory.getLogger(BaseRequest.class);

    private static final String[] ignoreFields = {"timeColumn"};
    /**
     * 时间选择: 开始时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE)
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    //    @Temporal(TemporalType.DATE)
    private String searchStartTime;

    /**
     * 时间选择: 结束时间
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd", iso = DateTimeFormat.ISO.DATE)
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    //    @Temporal(TemporalType.DATE)
    private String searchEndTime;

    /**
     * 时间列
     */
    private String timeColumn;

    public BaseRequest() {
    }

    /**
     * 将条件进行like拼接
     *
     * @param
     * @return
     */
    public QueryWrapper<T> getWrapper() {
        try {
            QueryWrapper<T> wrapper = new QueryWrapper<>();
            Class clzz = this.getClass();
            Field[] fields = clzz.getDeclaredFields();
            for (Field field : fields) {
                getSunField(field, wrapper);
            }
            getField(wrapper);
            return wrapper;
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
            return new QueryWrapper<>();
        }
    }

    /**
     * 将条件进行like拼接
     *
     * @param
     * @return
     */
    public QueryWrapper<T> getWrapper(QueryWrapper<T> wrapper) {
        try {
            Class clzz = this.getClass();
            Field[] fields = clzz.getDeclaredFields();
            for (Field field : fields) {
                getSunField(field, wrapper);
            }
            getField(wrapper);
            return wrapper;
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
            return new QueryWrapper<>();
        }
    }

    /**
     * 将条件进行eq拼接
     *
     * @return
     */
    public QueryWrapper<T> getEqWrapper(QueryWrapper<T> wrapper) {
        try {
            Class clzz = this.getClass();
            Field[] fields = clzz.getDeclaredFields();
            for (Field field : fields) {
                getSunEqField(field, wrapper);
            }
            getField(wrapper);
            return wrapper;
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
            return new QueryWrapper<>();
        }
    }

    /**
     * 将条件进行eq拼接
     *
     * @return
     */
    public QueryWrapper<T> getEqWrapper() {
        try {
            QueryWrapper<T> wrapper = new QueryWrapper<>();
            Class clzz = this.getClass();
            Field[] fields = clzz.getDeclaredFields();
            for (Field field : fields) {
                getSunEqField(field, wrapper);
            }
            getField(wrapper);
            return wrapper;
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
            return new QueryWrapper<>();
        }
    }


    /**
     * 拼接sql
     *
     * @param wrapper
     */
    private void getField(QueryWrapper<T> wrapper) {
        try {
            if (StringUtils.isNoneBlank(this.getTimeColumn())) {
                if (StringUtils.isNoneBlank(this.searchStartTime) || StringUtils.isNoneBlank(this.searchEndTime)) {
                    wrapper.and(w->{
                        w.ge(StringUtils.isNoneBlank(this.searchStartTime), convertToUnderline(this.getTimeColumn()), this.searchStartTime)
                                .le(StringUtils.isNoneBlank(this.searchEndTime), convertToUnderline(this.getTimeColumn()), this.searchEndTime);
                    });
                }
            }
        } catch (Exception e) {
            LOGGER.error(" requestconvert error: {}", e.getMessage());
        }
    }

    /**
     * 根据{@link Field} 拼接sql
     *
     * @param field
     * @param wrapper
     */
    private void getSunField(Field field, QueryWrapper<T> wrapper) {
        try {
            field.setAccessible(true);
            Object object = field.get(this);
            if ( object != null && !"".equals(object) && !"null".equals(object)) {
                wrapper.and(w->{
                    w.eq(StringUtils.isNotBlank(String.valueOf(object)), convertToUnderline(field.getName()), object);
                });
            }
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
        }
    }

    /**
     * 根据{@link Field} 拼接sql
     *
     * @param field
     * @param wrapper
     */
    private void getSunEqField(Field field, QueryWrapper<T> wrapper) {
        try {
            field.setAccessible(true);
            Object object =field.get(this);
            if (object != null && !"".equals(object) && !"null".equals(object)) {
                wrapper.and(w->{
                    w.eq(StringUtils.isNotBlank(String.valueOf(object)), convertToUnderline(field.getName()), object);
                });
            }
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
        }
    }

    /**
     * 根据{@link Field} 拼接sql
     *
     * @param field
     * @param wrapper
     */
    private void getSunAutoField(Field field, QueryWrapper<T> wrapper, List<String> specialList) {
        try {
            field.setAccessible(true);
            Object object =  field.get(this);
            if ( !specialList.contains(object) && object != null && !"".equals(object) && !"null".equals(object)) {
                wrapper.and(w->{
                    w.eq(convertToUnderline(field.getName()), object);
                });
            } else {
                wrapper.and(w->{
                    w.like(convertToUnderline(field.getName()), object);
                });
            }
        } catch (Exception e) {
            LOGGER.error("request convert error: {}", e.getMessage());
        }
    }

    /**
     * 驼峰字符转换成下划线
     *
     * @param param
     * @return
     */
    public String convertToUnderline(String param) {
        StringBuilder sb = new StringBuilder(param);
        int temp = 0;
        for (int i = 0; i < param.length(); i++) {
            if (Character.isUpperCase(param.charAt(i))) {
                sb.insert(i + temp, "_");
                temp += 1;
            }
        }
        return sb.toString().toUpperCase();
    }

}
